#ifndef JLIB_BITS_ASM_H
#define JLIB_BITS_ASM_H

namespace jlib {

inline bool bit_test (const void *bmp, unsigned int idx) noexcept {
  char res;
  asm volatile (R"(
    bt %[idx], (%[bmp])
    setc %[res]
    )"
  :[res]"=r"(res) :[bmp]"r"(bmp), [idx]"r"(idx));
  return res;
}

inline bool bit_test_and_set (const void *bmp, unsigned int idx) noexcept {
  char res;
  asm volatile (R"(
    bts %[idx], (%[bmp])
    setc %[res]
    )"
  :[res]"=r"(res) :[bmp]"r"(bmp), [idx]"r"(idx));
  return res;
}

inline bool bit_test_and_reset (const void *bmp, unsigned int idx) noexcept {
  char res;
  asm volatile (R"(
    btr %[idx], (%[bmp])
    setc %[res]
    )"
  :[res]"=r"(res) :[bmp]"r"(bmp), [idx]"r"(idx));
  return res;
}

inline bool bit_test_and_complement (const void *bmp, unsigned int idx) noexcept {
  char res;
  asm volatile (R"(
    btc %[idx], (%[bmp])
    setc %[res]
    )"
  :[res]"=r"(res) :[bmp]"r"(bmp), [idx]"r"(idx));
  return res;
}

inline void clear_direction () noexcept {
  asm volatile ("cld");
}

inline void memset (const void *mem, char val, unsigned int cnt) noexcept {
  asm volatile ("rep stosb" :[mem]"+&r"(mem), [cnt]"+&c"(cnt) :[val]"a"(val));
}

template<typename T>
inline T imod (T &dividend, T divisor) noexcept {
  T remainder = 0;
  asm volatile ("div %[divisor]" :"+&a"(dividend), "+&d"(remainder) :[divisor]"r"(divisor) :"cc");
  return remainder;
}



} // namespace jlib

#endif // JLIB_BITS_ASM_H
